package com.m3958.firstgwt.server.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;

import com.m3958.firstgwt.client.types.JsonExcludeFields;
import com.m3958.firstgwt.client.types.ObjectRoleName;
import com.m3958.firstgwt.server.types.HasObjectPermission;
import com.m3958.firstgwt.server.types.ObjectOperation;
import com.m3958.firstgwt.server.utils.JsonlibDateValueProssor;
import com.m3958.firstgwt.server.utils.ObjectPermissionUtil;

@Entity
@Table(name="TABLE_SCHEMA")
@AttributeOverride(name="id",column=@Column(nullable = false,name="TABLE_SCHEMA_ID"))
public class TableSchema extends BaseModel<TableSchema> implements HasCreator,HasObjectPermission{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	public static class NamedQueries{}
	
	
	private static ObjectOperation[] possibleOperations;
	
	private static ObjectRoleName[] possibleObjectRoles = ObjectRoleName.values();
	
	@Override
	public ObjectRoleName[] getPossibleRoleNames(){
		return possibleObjectRoles;
	}
	
	static{
		possibleOperations = ObjectOperation.values();
	}
	
	@Override
	public ObjectOperation[] getPossibleOperations(){
		return possibleOperations;
	}
	
	@Override
	public JSONObject toJson(){
		JsonConfig jc = new JsonConfig();
			jc.registerJsonValueProcessor(Date.class, injector.getInstance(JsonlibDateValueProssor.class));
			jc.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
			jc.setExcludes(JsonExcludeFields.TABLE_SCHEMA_EXCLUDES);

		return JSONObject.fromObject(this, jc);
	}
	
	private String name;
	
	private int position;
	
	private boolean anonymousRead;
	
	private boolean hasAuditField;
	
	private boolean hasPublicField;
	
	private int columnNum;
	
	@Lob
	private String fieldNameList;
	
	@Lob
	private String schemaJson;
	

	protected String creatorIds;
	
	@ManyToOne
	@JoinColumn(name="CREATOR_ID",referencedColumnName="USER_ID")
	protected User creator;
	
	
	@Override
	public User getCreator() {
		return creator;
	}

	@Override
	public void setCreator(User creator) {
		this.creator = creator;
		creatorIds = getCreatorPath(creator);
	}

	@Override
	public String getCreatorIds() {
		return creatorIds;
	}
	
	
	@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REMOVE})
	@JoinTable(name="FOLDER_OBJECTPERMISSION",
				joinColumns=
					@JoinColumn(name="FOLDER_FOLDER_ID"),
				inverseJoinColumns=
					@JoinColumn(name="OBJECTPERMISSIONS_PERMISSION_ID")
			)
	private List<Permission> objectPermissions = new ArrayList<Permission>();
	
	
	@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.REMOVE})
	@JoinTable(name="FOLDER_OBJECTROLE",
				joinColumns=
					@JoinColumn(name="FOLDER_FOLDER_ID"),
				inverseJoinColumns=
					@JoinColumn(name="OBJECTROLES_ROLE_ID")	
					
			)
	private List<Role> objectRoles = new ArrayList<Role>();
	
	@Override
	public List<Permission> getObjectPermissions() {
		return objectPermissions;
	}

	@Override
	public void setObjectPermissions(List<Permission> permissions) {
		this.objectPermissions = permissions;
	}
	
	
	@Override
	public void createObjectPermissions(){
		ObjectPermissionUtil.createObjectPermissions(this);
	}
	
	
	
	@Override
	public void createObjectRoles(){
		ObjectPermissionUtil.createObjectRoles(this);
	}
	
	@Override
	public Role createObjectRole(ObjectRoleName orn){
		return ObjectPermissionUtil.createObjectRole(this, orn);
	}
	
	@Override
	public Role getObjectRole(ObjectRoleName orn){
		return ObjectPermissionUtil.getObjectRole(this, orn);
	}
	
	public void setObjectRoles(List<Role> roles) {
		this.objectRoles = roles;
	}

	@Override
	public List<Role> getObjectRoles() {
		return objectRoles;
	}
	
	@Override
	public boolean addObjectRole(Role r){
		return ObjectPermissionUtil.addObjectRole(objectRoles, r);
	}
	
	@Override
	public boolean addObjectPermission(Permission p){
		return ObjectPermissionUtil.addObjectPermission(objectPermissions, p);
	}

	@Override
	public String getOname() {
		return name;
	}
	
	@Override
	public Permission getPermission(ObjectOperation opCode) {
		return ObjectPermissionUtil.getPermission(this, opCode);
	}


	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setPosition(int position) {
		this.position = position;
	}

	public int getPosition() {
		return position;
	}

	public void setSchemaJson(String schemaJson) {
		this.schemaJson = schemaJson;
	}

	public String getSchemaJson() {
		return schemaJson;
	}

	public boolean isAnonymousRead() {
		return anonymousRead;
	}

	public void setAnonymousRead(boolean anonymousRead) {
		this.anonymousRead = anonymousRead;
	}

	public boolean isHasAuditField() {
		return hasAuditField;
	}

	public void setHasAuditField(boolean hasAuditField) {
		this.hasAuditField = hasAuditField;
	}

	public boolean isHasPublicField() {
		return hasPublicField;
	}

	public void setHasPublicField(boolean hasPublicField) {
		this.hasPublicField = hasPublicField;
	}

	public void setFieldNameList(String fieldNameList) {
		this.fieldNameList = fieldNameList;
	}

	public String getFieldNameList() {
		return fieldNameList;
	}

	public void setColumnNum(int columnNum) {
		this.columnNum = columnNum;
	}

	public int getColumnNum() {
		return columnNum;
	}
}
